{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

Bokeh 5-minute Overview\n", "

\n", "\n", "Bokeh is an interactive web visualization library for Python \n", "(and other languages). It provides d3-like novel graphics, over\n", "large datasets, all without requiring any knowledge of Javascript. \n", "It has a Matplotlib compatibility layer, and it works great with\n", "the IPython Notebook, but can also be used to generate standalone HTML.\n", "\n", "Simple Example\n", "--------------\n", "\n", "Here is a simple first example. First we'll import the `bokeh.plotting`\n", "module, which defines the graphical functions and primitives." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ " \n", " \n", " \n", " \n", "
\n", " \n", " BokehJS successfully loaded.\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "ename": "ImportError", "evalue": "cannot import name vplot", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mImportError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mbokeh\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplotting\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mfigure\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moutput_notebook\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshow\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvplot\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mImportError\u001b[0m: cannot import name vplot" ] } ], "source": [ "from bokeh.plotting import figure, output_notebook, show, vplot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we'll tell Bokeh to display its plots directly into the notebook.\n", "This will cause all of the Javascript and data to be embedded directly\n", "into the HTML of the notebook itself.\n", "(Bokeh can output straight to HTML files, or use a server, which we'll\n", "look at later.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we'll import NumPy and create some simple data." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from numpy import cos, linspace\n", "x = linspace(-6, 6, 100)\n", "y = cos(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we'll call Bokeh's `circle()` function to render a red circle at\n", "each of the points in x and y.\n", "\n", "We can immediately interact with the plot:\n", "\n", " * click-drag will pan the plot around.\n", " * mousewheel will zoom in and out\n", " \n", "(The toolbar is simply a default one that is available for all plots;\n", "this can be configured dynamically via the `tools` keyword argument.)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "p = figure(width=500, height=500)\n", "p.circle(x, y, size=7, color=\"firebrick\", alpha=0.5)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Bar Plot Example\n", "----------------\n", "\n", "Bokeh's core display model relies on *composing graphical primitives* which\n", "are bound to data series. This is similar in spirit to Protovis and D3,\n", "and different than most other Python plotting libraries (except for perhaps\n", "Vincent and other, newer libraries).\n", "\n", "A slightly more sophisticated example demonstrates this idea.\n", "\n", "Bokeh ships with a small set of interesting \"sample data\" in the `bokeh.sampledata`\n", "package. We'll load up some historical automobile mileage data, which is returned\n", "as a Pandas `DataFrame`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from bokeh.sampledata.autompg import autompg\n", "from numpy import array\n", "grouped = autompg.groupby(\"yr\")\n", "mpg = grouped[\"mpg\"]\n", "avg = mpg.mean()\n", "std = mpg.std()\n", "years = array(list(grouped.groups.keys()))\n", "american = autompg[autompg[\"origin\"]==1]\n", "japanese = autompg[autompg[\"origin\"]==3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For each year, we want to plot the distribution of MPG within that year." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "p = figure()\n", "\n", "p.quad(left=years-0.4, right=years+0.4, bottom=avg-std, top=avg+std, fill_alpha=0.4)\n", "\n", "p.circle(x=japanese[\"yr\"], y=japanese[\"mpg\"], size=8,\n", " alpha=0.4, line_color=\"red\", fill_color=None, line_width=2)\n", "\n", "p.triangle(x=american[\"yr\"], y=american[\"mpg\"], size=8, \n", " alpha=0.4, line_color=\"blue\", fill_color=None, line_width=2)\n", "\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# This kind of approach can be used to generate other kinds of interesting plots, like some of the following which are available on the [Bokeh web page](http://bokeh.pydata.org/en/latest). \n", "\n", "*(Click on any of the thumbnails to open the interactive version.)*\n", "\n", "\n", "\n", "\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Linked Brushing\n", "---------------\n", "\n", "To link plots together at a data level, we can explicitly wrap the data in a ColumnDataSource.\n", "This allows us to reference columns by name.\n", "\n", "We can use the \"select\" tool to select points on one plot, and the linked points\n", "on the other plots will highlight." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from bokeh.models import ColumnDataSource\n", "from bokeh.plotting import gridplot\n", "\n", "source = ColumnDataSource(autompg.to_dict(\"list\"))\n", "source.add(autompg[\"yr\"], name=\"yr\")\n", "\n", "plot_config = dict(plot_width=300, plot_height=300, tools=\"pan,wheel_zoom,box_zoom,box_select,lasso_select\")\n", "\n", "p = gridplot([[\n", " figure(**plot_config).circle(\"yr\", \"mpg\", color=\"blue\", title=\"MPG by Year\", \n", " source=source),\n", " \n", " figure(**plot_config).circle(\"hp\", \"displ\", color=\"green\", \n", " title=\"HP vs. Displacement\", source=source),\n", " \n", " figure(**plot_config).circle(\"mpg\", \"displ\", size=\"cyl\", line_color=\"red\", \n", " title=\"MPG vs. Displacement\", fill_color=None, source=source),\n", "]])\n", "\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Standalone HTML\n", "---------------\n", "\n", "In addition to working well with the Notebook, Bokeh can also\n", "save plots out into their own HTML files. Here is the bar plot\n", "example from above, but saving into its own standalone file.\n", "\n", "Note that when we call `show()`, a new browser tab is opened.\n", "(If we just wanted to save the file, we would use `save()` instead.)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from bokeh.plotting import output_file\n", "\n", "output_file(\"barplot.html\")\n", "\n", "p = figure()\n", "\n", "p.quad(left=years-0.4, right=years+0.4, bottom=avg-std, top=avg+std, \n", " fill_alpha=0.4)\n", "p.circle(x=japanese[\"yr\"], y=japanese[\"mpg\"], size=8, \n", " alpha=0.4, line_color=\"red\", fill_color=None, line_width=2)\n", "p.triangle(x=american[\"yr\"], y=american[\"mpg\"], size=8, \n", " alpha=0.4, line_color=\"blue\", fill_color=None, line_width=2)\n", "\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Server-based Plotting\n", "---------------------\n", "\n", "The above plots are all embedded fully inside the notebook. This means that if you nbconvert\n", "or ship the notebook file around, all the examples remain fully interactive.\n", "\n", "But what if your data exceeds what is reasonable to embed in a notebook or HTML file?\n", "\n", "Bokeh also supports storing data inside the bokeh server, which is launched at\n", "the command line:\n", "\n", " $ bokeh-server\n", " \n", "After this is run, then any of the examples in [`examples/plotting/server/`](https://github.com/bokeh/bokeh/tree/master/examples/plotting/server) can\n", "be run.\n", "\n", "This includes animated plots:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotting \"Apps\"\n", "---------------\n", "\n", "When the linked brushing and server-based operation are combined,\n", "you can build graphical \"applets\", which resemble things like\n", "what Crossfilter and others do. However, Bokeh provides the\n", "reactive object model across client and server, so these sorts\n", "of selections and interactions can trigger server-side code,\n", "which is implemented in Python.\n", "\n", "*(Click to launch the live app.)*\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Downsampling\n", "------------\n", "\n", "The Bokeh plot server also has basic downsampling capability.\n", "This is an area that is under active development, and is one\n", "of the core design goals for Bokeh. Currently only line and\n", "image plots are supported, but techniques are under development\n", "for better, semantic downsampling of other visual forms.\n", "\n", "The following interactive plot displays 4.2gb of historical\n", "ocean temperature data. The left slider moves through time,\n", "and the right and bottom sliders affect the bottom and right\n", "plots. When you zoom on the main plot area, the server performs\n", "realtime downsampling on the data cube, and only sends the \n", "relevant data to the client.\n", "\n", "*(Click to launch a new tab with the interactive app)*\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "BokehJS\n", "-------\n", "\n", "At its core, Bokeh consists of a Javascript library (named [BokehJS](https://github.com/bokeh/bokeh/tree/master/bokehjs)), and a Python binding which provides classes and objects that ultimately generate a JSON representation of the plot structure.\n", "\n", "You can read more about design and usage in the [BokehJS section of the Bokeh Developer Guide](http://bokeh.pydata.org/en/latest/docs/dev_guide/bokehjs.html).\n", "\n", "BokehJS can be used entirely from Javascript. For instance, here is an embedded [JSFiddle](http://jsfiddle.net) that allows you to manipulate a plot. Click the \"Edit in JSFiddle\" to launch a JSFiddle window that lets you edit the Coffeescript source live:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import IFrame\n", "IFrame(\"http://jsfiddle.net/bokeh/Tw5Sm/embedded/result%2Cjs/\", 650, 700)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More Information\n", "----------------\n", "\n", "Full documentation and live examples: http://bokeh.pydata.org/en/latest\n", "\n", "GitHub: https://github.com/bokeh/bokeh\n", "\n", "Mailing list: [bokeh@continuum.io](mailto:bokeh@continuum.io)\n", "\n", "Be sure to follow us on Twitter [@bokehplots](http://twitter.com/BokehPlots>), as well as on [Youtube](https://www.youtube.com/channel/UCK0rSk29mmg4UT4bIOvPYhw) and [Vine](https://vine.co/bokehplots)!\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }